using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace InventorySystem
{
    public class GameItem : MonoBehaviour
    {
        [SerializeField]
        private ItemStack _stack;  // 物品堆栈
        private SpriteRenderer _spriteRenderer;  // 精灵渲染器

        // 属性获取物品堆栈，用于外部访问
        public ItemStack Stack => _stack;

        [Header("丢弃设置")]
        [SerializeField]
        private float _colliderEnabledAfter = 1f; // 多少秒后启用碰撞器
        [SerializeField]
        private float _throwGravity = 2f; // 扔出的物品受到的重力系数
        [SerializeField]
        private float _minThrowXForce = 3f; // 扔出物品时在X轴方向最小的力量值
        [SerializeField]
        private float _maxThrowXForce = 5f; // 扔出物品时在X轴方向最大的力量值
        [SerializeField]
        private float _throwYForce = 5f; // 扔出物品时在Y轴方向的力量值
        private Collider2D _collider; // 碰撞器
        private Rigidbody2D _rb; // 刚体

        // 初始化
        private void Awake()
        {
            _collider = GetComponent<Collider2D>();
            _rb = GetComponent<Rigidbody2D>();
            _collider.enabled = false; // 防止在还没扔出时被玩家拾取
        }

        // 开始游戏时的初始化
        private void Start()
        {
            SetupGameObject(); // 设置游戏对象
            StartCoroutine(EnableCollider(_colliderEnabledAfter)); // 在设定的时间后启用碰撞器
        }

        // 等待一段时间后启用碰撞器
        private IEnumerator EnableCollider(float afterTime)
        {
            yield return new WaitForSeconds(afterTime);
            _collider.enabled = true;
        }

        // 扔出物品
        public void Throw(float xDir)
        {
            _rb.gravityScale = _throwGravity; // 设定重力值
            var throwXForce = Random.Range(_minThrowXForce, _maxThrowXForce); // 随机力量值
            _rb.velocity = new Vector2(Mathf.Sign(xDir) * throwXForce, _throwYForce); // 设定物体的速度向量
            StartCoroutine(DisableGravity(_throwYForce));
        }

        // 一定的高度后禁用重力，让物品飞行更自然
        private IEnumerator DisableGravity(float atYVelocity)
        {
            yield return new WaitUntil(() => _rb.velocity.y < -atYVelocity);
            _rb.velocity = Vector2.zero;
            _rb.gravityScale = 0;
        }

        // 设定物品堆栈
        public void SetStack(ItemStack itemStack)
        {
            _stack = itemStack;
        }

        // 当对象检验时被调用,只要程序员在这个对象上修改了一个字段，Unity就会自动地调用这个函数。
        private void OnValidate()
        {
            SetupGameObject(); // 设置游戏对象
        }

        // 设置游戏对象
        private void SetupGameObject()
        {
            if (_stack.Item == null) return; // 如果物品为空，返回
            SetGameSprite(); // 设置游戏精灵
            AdjustNumberOfItems(); // 调整物品数量
            UpdateGameObjectName(); // 更新游戏对象名称
        }

        // 设置游戏精灵
        private void SetGameSprite()
        {
            _spriteRenderer = GetComponent<SpriteRenderer>();
            _spriteRenderer.sprite = _stack.Item.InGameSprite;
        }

        // 更新游戏对象名称
        private void UpdateGameObjectName()
        {
            var name = _stack.Item.Name;
            var number = _stack.IsStackable ? _stack.NumberOfItems.ToString() : "ns"; // 判断物品是否可堆叠
            gameObject.name = $"{name} ({number})"; // 修改游戏对象名称
        }

        // 调整物品数量
        private void AdjustNumberOfItems()
        {
            _stack.NumberOfItems = _stack.NumberOfItems;
        }

        //拾取物品方法
        public ItemStack Pick()
        {
            Destroy(gameObject);
            return _stack;
        }
    }
}
